package cn.com.cetccst.appstore.jssdk;

import static cn.com.cetccst.appstore.jssdk.CXApiImplInnerApp.CX_TYPE_WEB;

import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.webkit.ValueCallback;
import android.webkit.WebView;

import androidx.databinding.Observable;
import androidx.fragment.app.FragmentActivity;
import androidx.lifecycle.ViewModelProvider;

import cn.com.cetccst.appstore.jssdk.viewmodel.JSSDKViewModel;
import cn.com.cetccst.appstore.log.AppStoreLogger;
import cn.com.cetccst.appstore.tools.Utils;
import cn.com.cetccst.hostsdk.internal.SDKErrorCode;


public class CXJSInterface {
    private static final String TAG = "CXJSInterface";

    public static final String functionDomain = "CXJSInterface";

    private final WebView webView;
    private final FragmentActivity activity;
    private final CXApiImplInnerApp icxapi;
    private final Handler handler;
    private JSSDKViewModel viewModel;
    private String contextParams;

    private Observable.OnPropertyChangedCallback lifecycleListenerObserver = new Observable.OnPropertyChangedCallback() {
        @Override
        public void onPropertyChanged(Observable sender, int propertyId) {
            String listenerName = viewModel.lifecycleSource.get();
            BaseJSAction.Resp<String> resp = new BaseJSAction.Resp();
            resp.code = SDKErrorCode.ERROR_OK;
            resp.data = listenerName;
            String respJson = Utils.getGson().toJson(resp);
            if (JSSDKViewModel.LISTENER_LIFECYCLE_SHOW.equals(listenerName)) {
                if (!TextUtils.isEmpty(viewModel.showListener))
                    responseToJS(viewModel.showListener, respJson);
            } else if (JSSDKViewModel.LISTENER_LIFECYCLE_HIDE.equals(listenerName)) {
                if (!TextUtils.isEmpty(viewModel.hideListener))
                    responseToJS(viewModel.hideListener, respJson);
            }
        }
    };

    public CXJSInterface(FragmentActivity activity, WebView webView, String contextParams) {
        this.activity = activity;
        this.webView = webView;
        this.handler = new Handler(Looper.getMainLooper());
        this.contextParams = contextParams;
        icxapi = new CXApiImplInnerApp(activity, CX_TYPE_WEB);
        viewModel = new ViewModelProvider(activity).get(JSSDKViewModel.class);
        viewModel.lifecycleSource.addOnPropertyChangedCallback(lifecycleListenerObserver);
    }

    @android.webkit.JavascriptInterface
    public void request(String action, String paramsJson, String callbackName, String listener) {
        if (!isTrustDomain()) {
            defaultResponse(action, callbackName);
            return;
        }
        switch (action) {
            case ActionDownloadFile.ACTION:
                new ActionDownloadFileProgress(activity, icxapi, paramsJson, viewModel).handleAction(respJson -> {
                    responseToJS(callbackName, respJson);
                }, TextUtils.isEmpty(listener) ? null : respJson -> {
                    responseToJS(listener, respJson);
                });
                break;
            case ActionGetCanUse.ACTION:
                BaseJSAction getCanUseAction = new ActionGetCanUse(activity, icxapi, paramsJson);
                getCanUseAction.handleAction(respJson -> {
                    responseToJS(callbackName, respJson);
                });
                break;
            case ActionCancelDownloadFile.ACTION:
                new ActionCancelDownloadFile(activity, icxapi, paramsJson, viewModel).handleAction(respJson -> {
                    responseToJS(callbackName, respJson);
                });
                break;
            default:
                defaultResponse(action, callbackName);
                break;
        }
    }

    private void defaultResponse(String action, String callbackName) {
        new ActionDefault(activity, icxapi, action).handleAction(respJson -> {
            responseToJS(callbackName, respJson);
        });
    }

    private boolean isTrustDomain() {

        String currentUrl = viewModel.currentUrl.getValue();
        String trustDomains = viewModel.trustDomains.getValue();

        if (TextUtils.isEmpty(trustDomains)) {
            return true;
        }

        if (TextUtils.isEmpty(currentUrl)) {
            return false;
        }

        String[] domains = trustDomains.split(";");
        Uri uri = Uri.parse(currentUrl);
        String scheme = uri.getScheme();
        String host = uri.getHost();
        int port = uri.getPort();

        for (String domain : domains) {
            Uri domainUri = Uri.parse(domain);
            String domainScheme = domainUri.getScheme();
            String domainHost = domainUri.getHost();
            int domainPort = domainUri.getPort();
            if (scheme.equalsIgnoreCase(domainScheme) && host.equalsIgnoreCase(domainHost) && port == domainPort) {
                return true;
            }
        }

        return false;
    }

    @android.webkit.JavascriptInterface
    public void request(String action, String paramsJson, String callbackName) {
        request(action, paramsJson, callbackName, null);
    }

    protected void responseToJS(String callbackName, String para) {
        runOnUiThread(() -> {
            runJavaScriptFunction(callbackName, para);
        });
    }

    private void runJavaScriptFunction(ValueCallback<String> callback, String... params) {
        String cmd = "javascript:" + params[0] + "(";
        for (int i = 1; i < params.length; i++) {
//            cmd = cmd + "\"" + params[i] + "\"";
            cmd = cmd + params[i];
            if (i < params.length - 1) {
                cmd += ",";
            }
        }
        cmd += ")";
        AppStoreLogger.info(TAG, "runJavaScriptFunction:" + cmd);
        webView.evaluateJavascript(cmd, callback);
    }

    private void runJavaScriptFunction(String... params) {
        runJavaScriptFunction(new ValueCallback<String>() {
            @Override
            public void onReceiveValue(String s) {
            }
        }, params);
    }

    private void runOnUiThread(Runnable action) {
        if (Looper.myLooper() != Looper.getMainLooper()) {
            handler.post(action);
        } else {
            action.run();
        }
    }

    @android.webkit.JavascriptInterface
    public void registerListener(String paramsJson, String callbackName) {
        AppStoreLogger.info(TAG, "registerListener params:" + paramsJson + " callback:" + callbackName);
        new ActionRegisterListener(activity, icxapi, paramsJson).handleAction(respJson -> {
            responseToJS(callbackName, respJson);
        });
    }

    @android.webkit.JavascriptInterface
    public void unregisterListener(String paramsJson, String callbackName) {
        AppStoreLogger.info(TAG, "unregisterListener params:" + paramsJson + " callback:" + callbackName);
        new ActionUnregisterListener(activity, icxapi, paramsJson).handleAction(respJson -> {
            responseToJS(callbackName, respJson);
        });
    }

}